package driver.handlers;

import network.managers.ObserverManager;
import messages.udp.PersonInElevatorMessage;
import messages.udp.PersonOutElevatorMessage;
import messages.udp.PersonPressButtonMessage;
import messages.udp.PersonTransferMessage;
import driver.ActionDriver;
import driver.actions.HallCallAction;
import driver.actions.StandardPersonAction;
import state.group.events.BaseEvent;
import state.group.events.DoorEvent;
import state.person.Person;
import state.person.PersonState;
import state.person.events.PersonRegisterEvent;
import system.GlobalData;

public class BasicHandler extends BasePersonTypeHandler {

    @Override
    public void handleCreation(Person p)
    {        
        HallCallAction action = new HallCallAction(p.getHallCall());

        ActionDriver.getInstance().executeAction(0, action);
        
        ObserverManager.getInstance().postEvent(new PersonRegisterEvent(p));
    }

    @Override
    protected void handleWaiting(BaseEvent message, Person p)
    {
        switch (message.getEventType())
        {
            case DoorEvent:
                DoorEvent event = (DoorEvent) message;
                byte eleId = event.getElevatorId();

                if (GlobalData.partialState.get(eleId).getLastKnownFloor() == p.getHallCall().getFloor() && event.isOpen() == 1)
                {
                    synchronized (p)
                    {
                        p.setBusy();
                    }
                    
                    PersonPressButtonMessage pressMess = new PersonPressButtonMessage(p.getDestination());
                    StandardPersonAction pressButton = new StandardPersonAction(eleId, p, PersonState.inside, pressMess);

                    PersonInElevatorMessage doneMess = new PersonInElevatorMessage();
                    StandardPersonAction finishGoingIn = new StandardPersonAction(eleId, p, PersonState.inside, doneMess, pressButton, 2000);

                    PersonTransferMessage transMess = new PersonTransferMessage(PersonTransferMessage.GOING_IN, p.getWeight());
                    StandardPersonAction startGoingIn = new StandardPersonAction(eleId, p, PersonState.goingIn, transMess, finishGoingIn, 2000);
                    
                    ActionDriver.getInstance().executeAction(0, startGoingIn);
                }
        }
    }

    @Override
    protected void handleGoingIn(BaseEvent message, Person p)
    {

    }

    @Override
    protected void handleInside(BaseEvent message, Person p)
    {
        switch (message.getEventType())
        {
            case DoorEvent:
                DoorEvent event = (DoorEvent) message;
                byte eleId = event.getElevatorId();

                if (GlobalData.partialState.get(eleId).getLastKnownFloor() == p.getDestination() && event.isOpen() == 1)
                {
                    synchronized (p)
                    {
                        p.setBusy();
                    }

                    PersonOutElevatorMessage doneMess = new PersonOutElevatorMessage();
                    StandardPersonAction finishGoingOut = new StandardPersonAction(eleId, p, PersonState.atDestination, doneMess);

                    PersonTransferMessage transMess = new PersonTransferMessage(PersonTransferMessage.GOING_OUT, p.getWeight());
                    StandardPersonAction startGoingOut = new StandardPersonAction(eleId, p, PersonState.goingOut, transMess, finishGoingOut, 2000);
                    
                    ActionDriver.getInstance().executeAction(0, startGoingOut);
                }
        }
    }

    @Override
    protected void handleGoingOut(BaseEvent message, Person p)
    {

    }

    @Override
    protected void handleDestination(BaseEvent message, Person p)
    {

    }


}
